package com.weixing.mall.provider.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.weixing.mall.base.constant.DatePattern;
import com.weixing.mall.base.constant.GlobalConstant;
import com.weixing.mall.base.enums.IdGenTagEnum;
import com.weixing.mall.base.enums.SnCodeEnum;
import com.weixing.mall.base.exception.BusinessException;
import com.weixing.mall.base.wrapper.Result;
import com.weixing.mall.base.enums.WhetherEnum;
import com.weixing.mall.core.support.auth.SysAuth;
import com.weixing.mall.provider.api.model.vo.*;
import com.weixing.mall.provider.api.service.ActivityRpcService;
import com.weixing.mall.provider.api.service.ItemFeign;
import com.weixing.mall.provider.api.service.OrderServiceRpc;
import com.weixing.mall.provider.api.service.SysUserRpcService;
import com.weixing.mall.provider.mapper.InDepotBillMapper;
import com.weixing.mall.provider.mapper.InDepotBillProductMapper;
import com.weixing.mall.provider.mapper.ProductStockMapper;
import com.weixing.mall.provider.model.domain.*;
import com.weixing.mall.provider.model.dto.APPDepotDto;
import com.weixing.mall.provider.model.dto.InDepotBillDto;
import com.weixing.mall.provider.model.dto.InDepotBillProductDto;
import com.weixing.mall.provider.model.dto.InDepotChgIsFinishDto;
import com.weixing.mall.provider.model.enums.DepotTypeEunm;
import com.weixing.mall.provider.model.query.DepotBillDetilQuery;
import com.weixing.mall.provider.model.query.InDepotBillQuery;
import com.weixing.mall.provider.model.vo.InDepotBillVo;
import com.weixing.mall.provider.service.*;
import com.weixing.mall.provider.util.DepotUtil;
import com.weixing.mall.util.ListUtil;
import com.weixing.mall.util.SKUUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 仓库模块-入库单 服务实现类
 * </p>
 *
 * @author Small
 * @since 2019-11-15
 */
@Service
public class InDepotBillServiceImpl extends ServiceImpl<InDepotBillMapper, InDepotBill> implements IInDepotBillService {

    @Autowired
    private InDepotBillProductMapper inDepotBillProductMapper;
    @Autowired
    private IInDepotBillProductService inDepotBillProductService;
    @Autowired
    private IGoodsTransBillService goodsTransBillService;
    @Autowired
    private ProductStockMapper productStockMapper;
    @Autowired
    private IProductStockService productStockService;
    @Autowired
    private ItemFeign itemFeign;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private OrderServiceRpc orderServiceRpc;
    @Autowired
    private IDepotExtraService depotExtraService;
    @Autowired
    private IDepotService depotService;
    @Autowired
    private IProductStockDetailsService productStockDetailsService;
    @Autowired
    private IDefectiveProductService defectiveProductService;
    @Autowired
    private SysUserRpcService sysUserRpcService;
    @Autowired
    private ActivityRpcService activityRpcService;
    @Override
    public IPage selectOfPage(Page page, InDepotBillQuery inDepotBillQuery) {
        return baseMapper.selectOfPage(page, inDepotBillQuery);
    }

    @Override
    @Transactional
    public long save(InDepotBillDto inDepotBillDto, Long uid) {

        InDepotBill inDepotBill = new InDepotBill();
        BeanUtils.copyProperties(inDepotBillDto, inDepotBill);
        if (null != inDepotBillDto.getInDepotType()) {
            inDepotBill.setInDepotType(inDepotBillDto.getInDepotType().getValue());
        }
        inDepotBill.setIsFinish(inDepotBillDto.getIsFinish().getValue());
        if (null == inDepotBillDto.getId()) {
            inDepotBill.setCreatedBy(uid);
            inDepotBill.setBillSn(inDepotBillDto.getBillSn());
            //保存入库单
            baseMapper.insert(inDepotBill);
            //入库单id
            long inDepotId = inDepotBill.getId();
            if (inDepotBillDto.getProducts().size() > 0) {
                //入库单相关连商品list
                List<InDepotBillProductDto> list = inDepotBillDto.getProducts();
                List<InDepotBillProduct> insertList = Lists.newArrayList();
                for (int i = 0; i < list.size(); i++) {
                    InDepotBillProductDto inDepotBillProductDto = list.get(i);
                    if (inDepotBillProductDto.getQuantity() <= 0) {
                        continue;
                    }
                    InDepotBillProduct inDepotBillProduct = new InDepotBillProduct();
                    BeanUtils.copyProperties(inDepotBillProductDto, inDepotBillProduct);
                    inDepotBillProduct.setCreatedBy(uid);
                    inDepotBillProduct.setId(null);
                    //每条商品list添加入库单
                    inDepotBillProduct.setInDepotId(inDepotId);
                    //保存关联商品
                    insertList.add(inDepotBillProduct);
                    //  inDepotBillProductMapper.insert(inDepotBillProduct);
                }
                inDepotBillProductService.saveBatch(insertList, ListUtil.SIZE);
            }

            return inDepotId;
        } else {
            long inDepotId = inDepotBill.getId();
            inDepotBill.setUpdatedBy(uid);
            inDepotBill.setUpdatedTime(new Date());
            //修改入库单
            baseMapper.updateById(inDepotBill);
            if (inDepotBillDto.getProducts().size() > 0) {
                //入库单相关连商品list
                List<InDepotBillProductDto> list = inDepotBillDto.getProducts();
                inDepotBillProductMapper.delete(new QueryWrapper<InDepotBillProduct>().eq("in_depot_id", inDepotId));
                List<InDepotBillProduct> insertList = Lists.newArrayList();
                for (int i = 0; i < list.size(); i++) {
                    InDepotBillProductDto inDepotBillProductDto = list.get(i);
                    InDepotBillProduct inDepotBillProduct = new InDepotBillProduct();
                    BeanUtils.copyProperties(inDepotBillProductDto, inDepotBillProduct);
                    inDepotBillProduct.setUpdatedBy(uid);
                    inDepotBillProduct.setInDepotId(inDepotBill.getId());
                    inDepotBillProduct.setUpdatedTime(new Date());
                    inDepotBillProduct.setId(null);
                    //修改关联商品  TODO 优化批量插入
                    insertList.add(inDepotBillProduct);
                    // inDepotBillProductMapper.insert(inDepotBillProduct);
                }
                inDepotBillProductService.saveBatch(insertList,ListUtil.SIZE);
            }
            return inDepotId;
        }

    }

    @Override
    public void inDepotChgIsFinish(InDepotChgIsFinishDto inDepotChgIsFinishDto) {
        inDepotChgIsFinishDto.setInDepotTime(new Date());
        //更改库存

        baseMapper.inDepotChgIsFinish(inDepotChgIsFinishDto);
    }

    @Override
    public IPage getInDepotBillDetilList(Page page, DepotBillDetilQuery depotBillDetilQuery) {
        return inDepotBillProductMapper.getInDepotBillDetilList(page, depotBillDetilQuery);
    }

    @Override
    public InDepotBillVo getInDepotBillById(Long id) {
        return baseMapper.getInDepotBillById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void appSave(APPDepotDto appDepotDto, SysAuth auth) {
        /*第一步生成入库单并直接完成入库*/
        InDepotBill entity = new InDepotBill();
        // entity.setBillSn(goodsTransBillService.creatTransBill(SnCodeEnum.TRANSBILLSN.getValue()));
        entity.setBillSn(goodsTransBillService.creatTransBill(SnCodeEnum.INBILLSN.getValue()));//应该是生成入库单号
        entity.setInDepotType(DepotTypeEunm.TYPE_4.getValue());
        entity.setCreatedBy(auth.getUid());
        entity.setCreatedTime(new Date());
        entity.setInDepotTime(new Date());
        //TODO抛弃APP仓库ID号属性，进行后台查询获取
        Depot depot = depotService.getDepotByCode(GlobalConstant.DepotCode.APP);
        if (null == depot) {
            throw new BusinessException("仓库编号存在错误！");
        }
        if(null==appDepotDto.getDepotId()){
            appDepotDto.setDepotId(depot.getId());
        }
        entity.setInputDepot(depot.getId());
        //entity.setIsFinish(WhetherEnum.NO.getValue());
        entity.setIsFinish(WhetherEnum.YES.getValue());//不在审核直接入库更新库存
        baseMapper.insert(entity);
        /*RPC 调用获取商品信息*/
        ItemVo itemVo = itemFeign.findById(appDepotDto.getProductId()).getData();
        if (itemVo == null) {
            throw new BusinessException("调取商品信息服务异常");
        }
        /*入库操作*/
        InDepotBillProduct product = new InDepotBillProduct();
        product.setCreatedBy(auth.getUid());
        product.setCreatedTime(new Date());
        product.setGoodsId(itemVo.getGoodsId());
        product.setInDepotId(entity.getId());
        product.setProductId(itemVo.getId());
        product.setQuantity(1);
        product.setProductSn(itemVo.getProductSn());
        product.setGoodsSn(itemVo.getGoodsSn());
        product.setStyleNo(itemVo.getStyleNo());
        product.setGoodsName(itemVo.getProductName());
        product.setSpec(itemVo.getProductSkuDesp());
        inDepotBillProductMapper.insert(product);
        //TODO 新增仓库信息存储 z该属性在添加一个订单/ID和退货报表配合使用

        DepotExtra depotExtra = new DepotExtra();
        BeanUtils.copyProperties(appDepotDto, depotExtra);
        if (ObjectUtil.isNotEmpty(depotExtra)) {
            depotExtra.setCreatedBy(auth.getUid());
            depotExtra.setBusinessId(appDepotDto.getAfterSaleId());
            depotExtraService.save(depotExtra);
        }

        //二期项目库存流程进行了调整
        goOneProductDetails(appDepotDto,itemVo,auth);
        //TODO 在审核的时候进行库存更新
        /*//更新库存表  2020-6-28 要求直接入库变更库存数量 这里将原注释代码解开并加修改
        ProductStock stock = productStockMapper.selectOne(new QueryWrapper<ProductStock>().eq("product_id", itemVo.getProductId()).eq("depot_id", depot.getId()));
        if (ObjectUtil.isNotEmpty(stock)) {
            stock.setStock(stock.getStock() + 1);
            stock.setEnableStock(stock.getEnableStock() + 1);
            if (null != appDepotDto.getDepotLocation() || !"".equals(appDepotDto.getDepotLocation().trim())) {
                stock.setStorehouse(appDepotDto.getDepotLocation());
            }
            stock.setUpdatedBy(auth.getUid());
            stock.setUpdatedTime(new Date());
            stock.setStockSn(appDepotDto.getDepotSn());
            productStockMapper.updateById(stock);
        } else {
            stock = new ProductStock();
            stock.setStorehouse(appDepotDto.getDepotLocation());
            stock.setUpdatedBy(auth.getUid());
            stock.setUpdatedTime(new Date());
            stock.setStockSn(appDepotDto.getDepotSn());
            stock.setDepotId(depot.getId());
            stock.setProductId(itemVo.getProductId());
            stock.setGoodsId(itemVo.getGoodsId());
            stock.setProductSkuDesp(itemVo.getProductSkuDesp());
            stock.setProductSn(itemVo.getProductSn());
            stock.setStyleNo(itemVo.getStyleNo());
            stock.setEnableStock(1);
            stock.setStock(1);
            productStockMapper.insert(stock);
        }*/
        //变更售后表审核结果
        Result result = orderServiceRpc.updateAfterSaleStatus(appDepotDto.getAfterSaleId(), 1, auth.getUid(), auth.getRealName());
       /* if (!result.isSuccess()) {
            throw new BusinessException("订单服务结果变更调用失败");
        }*/
        //保存仓库信息 2020.9.1新增保存库位信息（调增）
        orderServiceRpc.updateDepotInfo(appDepotDto.getAfterSaleId(), appDepotDto.getDepotSn(), appDepotDto.getDepotLocation(), appDepotDto.getDepotOrder());
    }

    /**
     * 二期项目APP仓库入库APP仓库增加库存
     * @param appDepotDto 前端APP入库提交参数
     * @param itemVo   入库的商品详情
     * @param auth 当前的操作人员
     */
    private void goOneProductDetails(APPDepotDto appDepotDto, ItemVo itemVo, SysAuth auth) {
        ProductStockDetails stockDetails=new ProductStockDetails();
        stockDetails.setProductImg(itemVo.getProductImg());
        stockDetails.setProductSkuDesp(itemVo.getProductSkuDesp());
        //库存编码
        stockDetails.setStockSn(appDepotDto.getDepotSn());
        stockDetails.setDepotId(appDepotDto.getDepotId());
        stockDetails.setCreatedBy(auth.getUid());
        stockDetails.setCreatedTime(new Date());
        stockDetails.setGoodsId(itemVo.getGoodsId());
        stockDetails.setGoodsSn(itemVo.getGoodsSn());
        stockDetails.setProductSn(itemVo.getProductSn());
        stockDetails.setProductId(itemVo.getProductId());
        stockDetails.setProductName(itemVo.getProductName());
        stockDetails.setMarkerPrice(itemVo.getMarketPrice());
        //库存序号
        stockDetails.setStockOrder(appDepotDto.getDepotOrder());
        //库位
        stockDetails.setStorehouse(appDepotDto.getDepotLocation());
        //库存价格
        stockDetails.setStockPrice(itemVo.getCostPrice());
        stockDetails.setStyleNo(itemVo.getStyleNo());
        productStockDetailsService.save(stockDetails);
    }

    @Override
    public InDepotBillVo findMaxId() {
        return baseMapper.findMaxId();
    }

    /*
     * 审核通过
     *
     * */
    @Override
    public Long saveAndAudit(InDepotBillDto inDepotBillDto, Long uid) {
        inDepotBillDto.setIsFinish(WhetherEnum.YES);
        save(inDepotBillDto, uid);
        Long depotId = inDepotBillDto.getInputDepot();
        List<InDepotBillProductDto> products = inDepotBillDto.getProducts();
        //二期逻辑，对入库为次品库的进行优化和调整
        Depot depot=depotService.getById(depotId);
        if(depot.getIsDefective().intValue()==WhetherEnum.YES.getValue().intValue()){//如果为次品库，则次品库数据进行梳理
            goInDefective(products,uid);
        }else{
            //二期进行库存优化操作，批量更新库存详情表，入库执行批量插入操作。
            //对于存在大批量的数据更新，对数据进行分批量操作。
            Long result = goProductDetails(products,depotId);
            return result == null ? null : result;
        }
        return  null;

        //二期逻辑删除该模块
        //TODO 测试逻辑正式删除
        /*    List<InDepotBillProduct>  list=inDepotBillProductMapper.selectList(new QueryWrapper<InDepotBillProduct>().eq("in_depot_id",inDepotBillDto.getId()));*/
     /*
        for (InDepotBillProductDto dto : products) {
            ProductStock stock = productStockMapper.selectOne(new QueryWrapper<ProductStock>().eq("depot_id", depotId).eq("product_id", dto.getProductId()));
            if (stock == null) {
                stock = new ProductStock();
                BeanUtils.copyProperties(dto, stock);
                if (dto.getQuantity().intValue() < 0) {
                    throw new BusinessException("库存不允许小于0");
                }
                stock.setStock(dto.getQuantity());
                stock.setEnableStock(dto.getQuantity());
                stock.setStorehouse(dto.getStorehouse());
                stock.setProductSkuDesp(dto.getSpec());
                stock.setDepotId(depotId);
                stock.setId(null);
                productStockMapper.insert(stock);
            } else {
                ProductStock tmp = new ProductStock();
                tmp.setId(stock.getId());
                if (dto.getQuantity().intValue() < 0) {
                    throw new BusinessException("库存不允许小于0");
                }
                tmp.setStock(stock.getStock() + dto.getQuantity());
                tmp.setEnableStock(stock.getEnableStock() + dto.getQuantity());
                tmp.setRevision(stock.getRevision() + 1);
                if (null != dto.getStorehouse()) {
                    if (!"".equals(dto.getStorehouse().trim())) {
                        dto.setStorehouse(dto.getStorehouse());
                    }

                }
                productStockMapper.updateById(tmp);
            }
        }*/
    }

    /**
     * 批量商品入次品库操作
     * @param products
     * @param uid
     */
    private void goInDefective(List<InDepotBillProductDto> products, Long uid) {
        try {
            int splitNumber = products.size() / GlobalConstant.BATCH_SIZE + 1;
            List<List<InDepotBillProductDto>> splitList = Lists.partition(products, splitNumber);
            for (List<InDepotBillProductDto> list : splitList) {
                List<DefectiveProduct> insertBathList = Lists.newArrayList();
                for (InDepotBillProductDto inDepotBillProductDto : list) {
                    for (int i = 0; i < inDepotBillProductDto.getQuantity(); i++) {
                        DefectiveProduct productStockDetails = new DefectiveProduct();
                        BeanUtils.copyProperties(inDepotBillProductDto, productStockDetails);
                        insertBathList.add(productStockDetails);
                    }
                }
                defectiveProductService.saveBatch(insertBathList,ListUtil.SIZE);
            }

        } catch (Exception e) {
            e.getMessage();

        }


    }

    /**
     * 二期优化，商品库存为按照实际数量进行存储。
     *
     * @param products
     * @return
     */
    private Long goProductDetails(List<InDepotBillProductDto> products,Long inDepotId) {
        try {
            int splitNumber = products.size() / GlobalConstant.BATCH_SIZE + 1;
            List<List<InDepotBillProductDto>> splitList = Lists.partition(products, splitNumber);
            for (List<InDepotBillProductDto> list : splitList) {
                List<ProductStockDetails> insertBathList = Lists.newArrayList();
                for (InDepotBillProductDto inDepotBillProductDto : list) {
                    for (int i = 0; i < inDepotBillProductDto.getQuantity(); i++) {
                        ProductStockDetails productStockDetails = new ProductStockDetails();
                        BeanUtils.copyProperties(inDepotBillProductDto, productStockDetails);
                        try{
                            ItemVo itemVo=itemFeign.findById(inDepotBillProductDto.getGoodsId()).getData();
                            productStockDetails.setMarkerPrice(itemVo.getMarketPrice());
                            productStockDetails.setStockPrice(itemVo.getCostPrice());
                        }catch (Exception e){

                        }
                        if(ObjectUtil.isNotNull(inDepotBillProductDto.getInDepotId())){
                            if(0==inDepotBillProductDto.getInDepotId().intValue()){
                                productStockDetails.setDepotId(inDepotId);
                            }else{
                                productStockDetails.setDepotId(inDepotBillProductDto.getInDepotId());
                            }
                        }

                        productStockDetails.setProductSkuDesp(inDepotBillProductDto.getSpec());

                        insertBathList.add(productStockDetails);
                    }
                }
                productStockDetailsService.saveBatch(insertBathList,ListUtil.SIZE);
            }

        } catch (Exception e) {
            e.getMessage();
            return 0L;
        }

        return null;
    }

    @Override
    public String getInBillSn(String prefix) {
        long liveTime = 86400L;
        String dateFmt = DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN);
        String key = IdGenTagEnum.DEPOT_IN_SN_REDIS.getValue() + dateFmt;
        RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
        Long increment = entityIdCounter.getAndIncrement();
        if ((null == increment || increment.longValue() == 0) && liveTime > 0) {//初始设置过期时间
            entityIdCounter.expire(liveTime, TimeUnit.SECONDS);
        }
        String result = DepotUtil.genTransBillSn(prefix, dateFmt, increment + 1);
        return result;
    }

    /**
     * 返回库存编码 订单服务失败，返回1，CMS服务失败，返回2，库位不符合要求返回3  用于前端提示那个服务失败，
     *
     * @param orderId  订单ID
     * @param serialNumber  序号
     * @param stockSn   库位
     * @return
     */
    @Override
    public String depotStockSn(Long orderId, String serialNumber, String stockSn) {

        if(null!=stockSn&&!stockSn.matches("^(?=.*[A-Z])(?=.*[0-9])[A-Z0-9]{1,6}$\"")){
            return  "3";
        }
        Result<OrderItemVo> orderVo=orderServiceRpc.selectById(orderId);
        if(!orderVo.isSuccess()){
             return  "1";
        }
        OrderItemVo orderItemVo= orderVo.getData();
        if(null==orderItemVo){
            return  "1";
        }
        OrderGoodItvmVo orderGoodItvmVo= orderServiceRpc.getOrderGoodById(orderId);
        if(null==orderGoodItvmVo){
            return "1";
        }
        Result<SysUserVo> userVoResult= sysUserRpcService.getById(orderItemVo.getCustomerId());
        if(!userVoResult.isSuccess()){
            return "2";
        }
        SysUserVo sysUserVo=userVoResult.getData();
        if(null==sysUserVo){
            return "2";
        }
        String actCode="";
        if(null!=orderItemVo.getActId()){
            Result<ActRpcVo> actRpcVoResult=  activityRpcService.selectById(orderItemVo.getActId());
            if(!actRpcVoResult.isSuccess()){
                return  "2";
            }
            actCode=actRpcVoResult.getData().getActCode();

        }else{
            actCode=GlobalConstant.ACT_CODE;
        }
        stockSn=null==stockSn?"":stockSn;
        String result=actCode+sysUserVo.getUserCode()+serialNumber+SKUUtils.size2(orderGoodItvmVo.getSkuDesp())+fromatData()+"--"+stockSn;
        return result;
    }

    /**
     * 返回当前特定日期格式，为年份后两位+月份+日期，为YYMMDD
     * @return
     */
    private String fromatData() {
        String date = new SimpleDateFormat("yyyyMMdd").format(new Date()).substring(2,8);
        return date;
    }

    public static void main(String[] args) {
        if(("12JKL").matches("^(?=.*[A-Z])(?=.*[0-9])[A-Z0-9]{1,6}$")) {
            System.out.println("密码为6至20位小写字母, 大写字母和数字的组合");
        } else {
            System.out.println("匹配失败");
        }
    }
}
